"""Jinja2 Templates 相关功能模块"""
import os
from typing import Union

from fastapi import Request
from sqlalchemy import select

from core.database import DBConnect
from core.models import Group, Member
from service.member_service import MemberImageService


def editor_macro(request: Request) -> str:
    """设置的社论 macros.html 返回文件路径的函数

    Args:
        request (Request): FastAPI Request 对象

    Returns:
        str: The Eadiers macros.html 文件路径
    """
    # 设计师是 '未使用' 如果它是一个设置或未指定设计器
    # textarea设置为使用.
    editor_name = request.state.editor
    if not request.state.use_editor or not editor_name:
        editor_name = "textarea"

    return editor_name + "/macros.html"


def get_editor_select(id: str, selected: str) -> str:
    """DHTML 设计师名单 SELECT 以格式获取

    Args:
        id (str): select 标签的 id 属性值
        selected (str): 默认情况下要选择的设计器的名称

    Returns:
        str: select 标签的 HTML 代码
    """
    html_code = []
    html_code.append(f'<select id="{id}" name="{id}">')

    if id == 'bo_select_editor':
        selected_attr = "selected" if selected == "" else ""
        html_code.append(f'<option value="" {selected_attr}>使用默认环境设置的设计器</option>')
    else:
        html_code.append(f'<option value="">未使用</option>')

    editor_path = os.path.join("static", "plugin", "editor")
    for editor in os.listdir(editor_path):
        if (editor == 'textarea'
                or not os.path.isdir(os.path.join(editor_path, editor))):
            continue
        attr = get_selected(editor, selected)
        html_code.append(f'<option value="{editor}" {attr}>{editor}</option>')

    html_code.append('</select>')

    return ''.join(html_code)


def get_group_select(id: str, selected: str = "", attribute: str = "") -> str:
    """公告板组列表 SELECT 以格式获取

    Args:
        id (str): select 标签的 id 属性值
        selected (str, optional): 默认选择的组名. Defaults to "".
        attribute (str, optional): select 标记的其他属性值. Defaults to "".

    Returns:
        str: select 标签的 HTML 代码
    """
    db = DBConnect().sessionLocal()
    groups = db.scalars(
        select(Group).order_by(Group.gr_order, Group.gr_id)
    ).all()
    db.close()

    html_code = []
    html_code.append(f'<select id="{id}" name="{id}" {attribute}>\n')
    html_code.append('<option value="">选择</option>')

    for group in groups:
        html_code.append(option_selected(
            group.gr_id, selected, group.gr_subject))

    html_code.append('</select>')

    return ''.join(html_code)


def get_member_id_select(id: str, level: int, selected: str, attribute=""):
    """会员的Idy SELECT 以格式获取

    Args:
        id (_type_): _description_
        level (_type_): _description_
        selected (_type_): _description_
        event (str, optional): _description_. Defaults to ''.

    Returns:
        _type_: _description_
    """
    db = DBConnect().sessionLocal()
    mb_ids = db.scalars(
        select(Member.mb_id)
        .where(Member.mb_level >= level)
    ).all()
    db.close()

    html_code = []
    html_code.append(f'<select id="{id}" name="{id}" {attribute}>')
    html_code.append('<option value="">选择</option>')

    for mb_id in mb_ids:
        attr = get_selected(mb_id, selected)
        html_code.append(f'<option value="{mb_id}" {attr}>{mb_id}</option>')

    html_code.append('</select>')

    return ''.join(html_code)


def get_member_level_select(id: str, start: int, end: int,
                            selected: int, attribute: str = '') -> str:
    """会员级别 SELECT 以格式获取

    Args:
        id (str): select 标签的 id 属性值
        start (int): 起始电平
        end (int): 结束级别
        selected (int): 默认情况下应选择的级别
        attribute (str, optional): select 标记的其他属性值. Defaults to "".

    Returns:
        str: _description_
    """
    html_code = []
    html_code.append(f'<select id="{id}" name="{id}" {attribute}>')

    for i in range(start, end + 1):
        attr = get_selected(i, selected)
        html_code.append(f'<option value="{i}" {attr}>{i}</option>')

    html_code.append('</select>')

    return ''.join(html_code)


def get_skin_select(skin_gubun: str, id: str, selected: str,
                    attribute: str = "", device: str = "") -> str:
    """skin_gubun(new, search, connect, faq 等等。)根据皮肤
    SELECT 以格式获取

    Args:
        skin_gubun (str): 主题内的文件夹名称(功能)
        id (str): select 标签的 id 属性值
        selected (str): 默认情况下选择的外观名称
        attribute (str, optional): select 标记的其他属性值. Defaults to "".
        device (str, optional): 文件夹名称 (按设备)(mobile). Defaults to "".
            PC没有附加路径 (ex: /templates/{theme}/board/{skin_gubun})
            PC는 추가 경로 없음 (ex: /templates/{theme}/board/{skin_gubun})

    Returns:
        str: select 标签的 HTML 代码
    """
    # Lazy import
    from core.template import TemplateService

    skin_path = TemplateService.get_templates_dir() + f"/{device}/{skin_gubun}"

    html_code = []
    html_code.append(f'<select id="{id}" name="{id}" {attribute}>')
    html_code.append('<option value="">选择</option>')

    for skin in os.listdir(skin_path) if os.path.isdir(skin_path) else []:
        if os.path.isdir(f"{skin_path}/{skin}"):
            attr = get_selected(skin, selected)
            html_code.append(f'<option value="{skin}" {attr}>{skin}</option>')

    html_code.append('</select>')

    return ''.join(html_code)


def get_selected(field_value, value):
    """通过比较存储在字段中的值和默认值 selected 返回.

    Args:
        field_value: 字段中存储的值
        value: 默认值

    Returns:
        str: 如果值匹配 'selected="selected"', 如果没有， ''
    """
    if ((field_value is None or field_value == '')
            or (value is None or value == '')):
        return ''

    return ' selected="selected"' if str(field_value) == str(value) else ''


def option_selected(value: str, selected: str, text = ''):
    """option 生成并返回标签

    Args:
        value (str): value 属性值
        selected (str): selected 属性值
        text (str, optional): _description_. Defaults to ''.

    Returns:
        str: option 标签
    """
    if not text:
        text = value

    select_attr = get_selected(value, selected)

    return f'<option value="{value}" {select_attr}>{text}</option>\n'


def option_array_checked(option: str, arr: Union[list, str] = []) -> str:
    """option这个 arr如果它包含在 checked="checked"返回

    Args:
        option (str): _description_
        arr (Union[list, str], optional): 要检查的值. Defaults to [].

    Returns:
        str: 'checked="checked"' 或 ''
    """
    if not isinstance(arr, list):
        arr = arr.split(',')

    if arr and option in arr:
        return 'checked="checked"'

    return ''


def get_paging(request: Request,
               current_page: int, total_count: int, page_rows: int = 0,
               add_url: str = ""):
    """页面输出功能

    nouboard5 get_paging() 与功能有什么不同
    1. 在接管中 write_pages 删除
    2. 在接管 total_page 而不是 total_count 已使用

    Args:
        request (Request): FastAPI Request 对象
        current_page (int): 当前页面
        total_count (int): 记录的总数
        page_rows (int, optional): 每页的行数. Defaults to 0.
        add_url (str, optional): 添加页面链接 URL. Defaults to "".

    Returns:
        str: 分页 HTML 代码
    """
    config = request.state.config
    url_prefix = request.url

    try:
        current_page = int(current_page)
    except ValueError:
        # current_page如果无法转换为整数，则为默认值 1设置为使用
        current_page = 1
    total_count = int(total_count)

    # 每页的行数
    if not page_rows:
        page_rows = config.cf_mobile_page_rows if request.state.is_mobile and config.cf_mobile_page_rows else config.cf_page_rows
    # 页面显示编号
    page_count = config.cf_mobile_pages if request.state.is_mobile and config.cf_mobile_pages else config.cf_write_pages

    # 右侧 total_pages 计算 (圆角处理)
    total_pages = (total_count + page_rows - 1) // page_rows

    # 页面链接列表的初始化
    page_links = []

    start_page = ((current_page - 1) // page_count) * page_count + 1
    end_page = start_page + page_count - 1

    # # 中央页面计算
    middle = page_count // 2
    start_page = max(1, current_page - middle)
    end_page = min(total_pages, start_page + page_count - 1)

    # 第一页链接创建
    if current_page > 1:
        start_url = f"{url_prefix.include_query_params(page=1)}{add_url}"
        page_links.append(f'<a href="{start_url}" class="page start" title="第一页"><i class="fa fa-backward-fast"></i><span class="blind">第一次</span></a>')

    # 上一页间隔链接创建
    if start_page > 1:
        prev_page = max(current_page - page_count, 1)
        prev_url = f"{url_prefix.include_query_params(page=prev_page)}{add_url}"
        page_links.append(f'<a href="{prev_url}" class="page prev" title="上一节"><i class="fa fa-caret-left"></i><span class="blind">上一个</span></a>')

    # 页面链接创建
    for page in range(start_page, end_page + 1):
        page_url = f"{url_prefix.include_query_params(page=page)}{add_url}"
        if page == current_page:
            page_links.append(f'<a href="{page_url}" class="page current" title="电流 {page} 페이지"><strong class="blind">현재</strong>{page}<strong class="blind">페이지</strong></a>')
            page_links.append(f'<a href="{page_url}" class="page current" title="电流 {page} 页数"><strong class="blind">현재</strong>{page}<strong class="blind">页数</strong></a>')
        else:
            page_links.append(f'<a href="{page_url}" class="page" title="{page} 页数">{page}</a>')

    # 下一页间隔链接创建
    if total_pages > end_page:
        next_page = min(current_page + page_count, total_pages)
        next_url = f"{url_prefix.include_query_params(page=next_page)}{add_url}"
        page_links.append(f'<a href="{next_url}" class="page next" title="下一节"><i class="fa fa-caret-right"></i><span class="blind">下一个</span></a>')
    
    # 最后一页链接创建
    if current_page < total_pages:
        end_url = f"{url_prefix.include_query_params(page=total_pages)}{add_url}"
        page_links.append(f'<a href="{end_url}" class="page end" title="最后一页"><i class="fa fa-forward"></i><span class="blind">最后的</span></a>')

    # 通过将页面链接列表转换为字符串返回
    return '<div class="pagination">' + ''.join(page_links) + '</div>'


def subject_sort_link(request: Request,
                      column: str, query_string: str = '', flag: str = 'asc') -> str:
    """在当前页面中，创建一个链接以根据列进行排序.

    Args:
        request (Request): FastAPI Request 对象
        column (str): 要排序的列名称
        query_string (str, optional): 查询字符串. Defaults to ''.
        flag (str, optional): 对齐方法. Defaults to 'asc'.

    Returns:
        str: 对齐链接
    """
    sst = request.query_params.get("sst", "")
    sod = request.query_params.get("sod", "")
    sfl = request.query_params.get("sfl", "")
    stx = request.query_params.get("stx", "")
    sca = request.query_params.get("sca", "")
    fr_date = request.query_params.get("fr_date", "")
    to_date = request.query_params.get("to_date", "")
    page = request.query_params.get("page", "")

    # q1最重要的是 column 添加一个值.
    q1 = f"sst={column}"

    if flag == 'asc':
        # flag对 'asc'如果, q2开 'sod=asc'分配.
        q2 = 'sod=asc'
        if sst == column:
            if sod == 'asc':
                # 在当前状态 sst和 col就像这样. sod对 'asc'如果, q2中国 'sod=desc'更改为.
                q2 = 'sod=desc'
    else:
        # flag对 'asc'如果没有, q2开 'sod=desc'分配.
        q2 = 'sod=desc'
        if sst == column:
            if sod == 'desc':
                # 在当前状态 sst和 col就像这样. sod对 'desc'如果, q2中国 'sod=asc'更改为.
                q2 = 'sod=asc'

    # query_string, q1, q2中国 arr_query 添加到列表.
    arr_query = []
    arr_query.append(query_string)
    arr_query.append(q1)
    arr_query.append(q2)

    # sfl, stx, sca, fr_date, to_date, page 如果值为 None如果没有, 每个的价值 arr_query添加到.
    if sfl is not None:
        arr_query.append(f'sfl={sfl}')
    if stx is not None:
        arr_query.append(f'stx={stx}')
    if sca is not None:
        arr_query.append(f'sca={sca}')
    if fr_date:
        arr_query.append(f'fr_date={fr_date}')
    if to_date:
        arr_query.append(f'to_date={to_date}')
    if page:
        arr_query.append(f'page={page}')

    # arr_query的第一个元素以外的其余元素 '&'通过连接到 qstr我们分配给.
    # arr_query의 첫 번째 요소를 제외한 나머지 요소를 '&'로 연결하여 qstr에 할당한다.
    qstr = '&'.join(arr_query[1:]) if arr_query else ''
    # qstr报告 '&'通过分离 pairs 保存到列表.
    pairs = qstr.split('&')

    # params 创建字典.
    params = {}

    # pairs 列表的每个元素 '='通过分离 key和 value并除以, value如果它不是空字符串 params添加到.
    for pair in pairs:
        if '=' in pair:
            key, value = pair.split('=')
            if value != '':
                params[key] = value

    # qstr使用作为查询字符串创建并返回链接.
    return f'<a href="?{qstr}">'


def get_member_icon(mb_id: str) -> str:
    # “模板函数返回成员图标路径”
    return MemberImageService.get_icon_path(mb_id)

def get_member_image(mb_id: str) -> str:
# “模板函数返回成员映像路径”
    return MemberImageService.get_image_path(mb_id)
